A slew of updates from Alex Mottram. Thanx!
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 15 Sep 2002 23:05:56 +0000 (23:05 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 15 Sep 2002 23:05:56 +0000 (23:05 +0000)
gpsbabel/README
gpsbabel/mxf.c
gpsbabel/psp.c
gpsbabel/testo

index 194820d67e3ca5a69fe5f69a7a1f9e675aa7c493..67801c46f252dbfd7593f6ee4f55d4205eacd1a5 100644 (file)
@@ -99,6 +99,7 @@ THE FORMATS
        write them.
        
     PSP
+
        Microsoft's PocketStreets 2002 Pushpin (.PSP) format is not yet 
        completely documented.  THE .PSP MODULE DOES NOT WORK WITH MS 
        STREETS & TRIPS 2002 .EST FILES.  To create .PSP files from 
@@ -114,6 +115,12 @@ THE FORMATS
        .MPS files.  Unfortunately, you need one .PSP file for every 
        .MPS file. :(
 
+    MXF
+
+       Maptech Exchange Format - Another CSV format file.  This format
+       complies with (at least) Maptech Terrain Navigator, Terrain
+       Professional, Take a Hike, and ExpertGPS import/export MFX.
+
   Maptech MXF
        Maptech's MXF is a CSV on steroids.  Contributed by Alex Mottram.
 
index e360efebc13b228dd4507278157dd63e7625de82..aa13f1f1923381af55087acdb00118c4ce5721f2 100644 (file)
@@ -1,14 +1,14 @@
 /*
     Mapsend Exchange Format (.mxf)
     (Maptech Terrain Navigator, Terrain Professional, Take a Hike)
-    (Aka Yet Another CSV Format) 
+    (AKA Yet Another CSV Format) 
 
-    Contributed to gpsbabel by Alex Mottram
+    Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com)
 
-    LAT,LON,"WPT Name", "Big Name","Small Name",COLORxFF,(int)ICON
+    LAT, LON, "Waypoint Name", "Big Name", "Small Name", COLOR, ICON
 
-    as described at: www.memory-map.co.uk/downloads/PDF/mm_tsb3_import_export_text_files.pdf 
-    tested against ExpertGPS import/export .mxf files.
+    As described in Maptech Terrain Navigator Help File.
+    Tested against Terrain Navigator and ExpertGPS import/export .MXF files.
 
     Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
 
@@ -36,9 +36,8 @@
 static FILE *file_in;
 static FILE *file_out;
 
-/* remember what dave & gamera say about pointer math... */
 static char * 
-cvsstringclean(char * string)
+csvstringclean(char * string)
 {
     static char * p1 = NULL;
     char * p2 = NULL;
@@ -73,7 +72,8 @@ cvsstringclean(char * string)
     return (p1);    
 }
 
-/* string parser.  sorta like strtok with quotes & pointers.. */
+/* string parser.  sorta like strtok with quotes & pointers..  */
+/* designed to handle quoted and delimited data within quotes. */
 static char * 
 csvparse(char *stringstart, char *delimiter)
 {
@@ -82,6 +82,7 @@ csvparse(char *stringstart, char *delimiter)
     static char *tmp = NULL;
     size_t dlen;
     int quotedepth = 0;
+    short int dfound;
 
     if (!p) {
        p = stringstart;
@@ -99,8 +100,9 @@ csvparse(char *stringstart, char *delimiter)
     sp = p;
 
     dlen = strlen(delimiter);
+    dfound = 0;
 
-    while ((*p) && (! tmp)) {
+    while ((*p) && (! dfound)) {
        if (*p == '"') {
            if (quotedepth) 
                quotedepth--;
@@ -109,32 +111,31 @@ csvparse(char *stringstart, char *delimiter)
        }
 
        if ((!quotedepth) && (strncmp(p, delimiter, dlen) == 0)) {
-               tmp = (char *) calloc((p - sp) + 1, sizeof(char));
-               if (! tmp) {
-                   fatal(MYNAME ": cannot allocate memory\n");
-               }
-               strncpy(tmp, sp, (p - sp));
+               dfound = 1;
+               
+       } else {
+               p++;
        }
-       p++;
-    }
-
-    if (!tmp) {
-       tmp = (char *) calloc((p - sp) + 1, sizeof(char));
 
-       if (! tmp) {
-           fatal(MYNAME ": cannot allocate memory\n");
-       }
+    }
 
-       strncpy(tmp, sp, (p - sp));
+    tmp = (char *) calloc((p - sp) + 1, sizeof(char));
 
-       p = NULL;
+    if (! tmp) {
+       fatal(MYNAME ": cannot allocate memory\n");
     }
 
-    if (tmp) {
-       return (tmp);
+    strncpy(tmp, sp, (p - sp));
+
+    if (dfound) {
+        /* skip over the delimiter */
+        p += dlen;
+    } else {
+        /* end of the line */
+        p = NULL;
     }
 
-    return (NULL);
+    return (tmp);
 }
 
 static void 
@@ -190,7 +191,7 @@ data_read(void)
            }
 
            s = buff;
-           s = csvparse(s, ",");
+           s = csvparse(s, ", ");
 
            i = 0;
            while (s) {
@@ -202,10 +203,10 @@ data_read(void)
                    wpt_tmp->position.longitude.degrees = atof(s);
                    break;
                case 2:
-                   wpt_tmp->description = strdup(cvsstringclean(s));
+                   wpt_tmp->description = strdup(csvstringclean(s));
                    break;
                case 3:
-                   wpt_tmp->shortname = strdup(cvsstringclean(s));
+                   wpt_tmp->shortname = strdup(csvstringclean(s));
                    break;
                case 4:
                     /* ignore.  another name-type  */
@@ -218,27 +219,25 @@ data_read(void)
                    break;
                default:
                    /* whoa! nelly */
-                   printf ("%s: Warning: data fields on line %d exceed specification.\n", 
+                   fprintf (stderr, "%s: Warning: data fields on line %d exceed specification.\n", 
                        MYNAME, linecount);
                    break;
                }
                i++;
 
-               s = csvparse(NULL, ",");
+               s = csvparse(NULL, ", ");
            }
            
            if (i != 7) {
                free(wpt_tmp);
-               printf ("%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n", 
+               fprintf (stderr, "%s: WARNING - extracted %d fields from line %d. \nData on line ignored.\n", 
                    MYNAME, i, linecount);
            } else {
                waypt_add(wpt_tmp);
            }
 
        } else {
-            /* this complains too much 
-            * printf ("%s: WARNING - blank line at line %d.\n", MYNAME, linecount);
-             */
+            /* empty line */
        }
 
     } while (!feof(file_in));
@@ -247,18 +246,13 @@ data_read(void)
 static void 
 mxf_disp(waypoint * wpt)
 {
-    double lon, lat;
     int icon = 47; /* default to "dot" */
     const char *color_hex = "ff0000";
 
-    lon = wpt->position.longitude.degrees;
-    lat = wpt->position.latitude.degrees;
-
     fprintf(file_out, "%08.5f, %08.5f, \"%s\", \"%s\", \"%s\", %s, %d\n",
-           lat, lon,
+           wpt->position.latitude.degrees, wpt->position.longitude.degrees,
            wpt->description, wpt->shortname, wpt->description, 
            color_hex, icon);
-
 }
 
 static void 
@@ -267,7 +261,6 @@ data_write(void)
     waypt_disp_all(mxf_disp);
 }
 
-
 ff_vecs_t mxf_vecs = {
     rd_init,
     wr_init,
@@ -277,15 +270,3 @@ ff_vecs_t mxf_vecs = {
     data_write,
 };
 
-
-/*
-    Excerpt from Maptech help file.
-
-    Below is an example of the .MXF file format:
-
-    43.7601389, -071.2791299, "Cottonwood", "Cttnwd", "A very large tree", 800080, 137
-    43.7617236, -071.2917695, "Fencepost", "Fncpst", "", 808080, 14
-    43.7576237, -071.2888850, "Aspen", "Aspen", "", ffff, 137
-    43.7562457, -071.2777147, "Cache", "Cache", "", ff, 138
-    43.7576583, -071.2701399, "Tent site", "Tntst", "", ff, 111
-*/
index c8a8f38fe11d15471deef2ec4f2d4db20c708966..18fd32a4de675dd306af8d081bcc5c48b0bce25d 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PocketStreets 2002 Pushpin Files
-    Contributed to gpsbabel by Alex Mottram.
+    Contributed to gpsbabel by Alex Mottram (geo_alexm at cox-internet.com)
     
     Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
 
  */
 
 #include "defs.h"
-
 #include <ctype.h>
 #include <math.h>  /* for M_PI */
 
-#define MYNAME "PSP"
+#define MYNAME "PSP"
 
-/*#define _DEBUG_PSP   1*/
 #define MAXPSPSTRINGSIZE       256
 #define MAXPSPOUTPUTPINS       8192   /* Any more points than this is ludicrous */
 
 static FILE *psp_file_in;
 static FILE *psp_file_out;
 
-#ifdef _DEBUG_PSP
-static void 
-dump_bufferstuff(char * header, char * buffer, int bufferlen)
-{
-    int i;
+static int
+psp_fread(void *buff, size_t size, size_t members, FILE * fp) {
+    size_t br;
 
-    printf("%s\n--------\n", header);
+    br = fread(buff, size, members, fp);
+
+    if (br != members) {
+        fatal(MYNAME ": requested to read %d bytes, read %d bytes.\n", members, br);
+    }
 
-    for (i = 0 ; i < bufferlen ; i++) {
-       printf("%0.2X ", (unsigned char)buffer[i]);
-    } 
-    printf("\n");
+    return (br);
+}
+
+static int
+valid_psp_header(char * header, int len) {
+    char header_bytes[] = { 0x31, 0x6E, 0x69, 0x50, 0x00 }; /* 1niP <stop> */
+    char *p, *s;
+
+    if (len != 32) {
+        return (-1);
+    }
+
+    p = header_bytes;
+    s = header;
+
+    while (*p) {
+        if (*p++ != *s++) {
+            return(-1);
+        }
+    }
+
+    return (0);
 }
-#endif
 
 static char *
 buffer_washer(char * buff, int buffer_len)
 {
     int i;
-    
+
     for (i = 0 ; i < buffer_len - 1; i++) {
        if (buff[i] == '\0') {
            memcpy(&buff[i], &buff[i+1], buffer_len - i);
@@ -68,7 +85,7 @@ buffer_washer(char * buff, int buffer_len)
 static void
 psp_rd_init(const char *fname)
 {
-       psp_file_in = fopen(fname, "r");
+       psp_file_in = fopen(fname, "rb");
        if (psp_file_in == NULL) {
                fatal(MYNAME ": Cannot open %s for reading\n", fname);
        }
@@ -83,7 +100,7 @@ psp_rd_deinit(void)
 static void
 psp_wr_init(const char *fname)
 {
-       psp_file_out = fopen(fname, "w");
+       psp_file_out = fopen(fname, "wb");
        if (psp_file_out == NULL) {
                fatal(MYNAME ": Cannot open %s for writing\n", fname);
        }
@@ -98,17 +115,21 @@ psp_wr_deinit(void)
 static void
 psp_read(void)
 {
-       char buff[MAXPSPSTRINGSIZE + 1]; 
+       char buff[MAXPSPSTRINGSIZE + 1];
        double radians;
        waypoint *wpt_tmp;
        int stringsize;
        short int pincount;
 
         /* 32 bytes - file header */
-        fread(&buff[0], 1, 32, psp_file_in);
-        
+        psp_fread(&buff[0], 1, 32, psp_file_in);
+
+        if (valid_psp_header(buff, 32) != 0) {
+            fatal(MYNAME ": input file does not appear to be a valid .PSP file.\n");
+        }
+
        pincount = *(short int *)&buff[12];
-       
+
        while (pincount--) {
            wpt_tmp = calloc(sizeof(*wpt_tmp),1);
 
@@ -119,68 +140,64 @@ psp_read(void)
            /* things we will probably never know about this waypoint */
            /* coming from a pushpin file.                            */
 
-           /* 
+           /*
                wpt_tmp->creation_time;
                wpt_tmp->position.altitude.altitude_meters;
                wpt_tmp->url;
                wpt_tmp->url_link_text;
                wpt_tmp->icon_descr;  TODO: map this.
            */
-           
+
             /* 4 bytes at start of record */
             /* coming out of S&T, this 1st byte is probably the pin # (0x01, 0x02, etc...) */
             /* coming from pocketstreets, it's generally 0x00. Sometimes 0xC3. ?           */
-            
-           fread(&buff[0], 1, 4, psp_file_in);
+
+           psp_fread(&buff[0], 1, 4, psp_file_in);
 
             /* 1 byte, unkown */
-            fread(&buff[0], 1, 1, psp_file_in);
+            psp_fread(&buff[0], 1, 1, psp_file_in);
 
             /* 8 bytes - latitude in radians */
-            fread(&buff[0], 1, 8, psp_file_in);
+            psp_fread(&buff[0], 1, 8, psp_file_in);
             radians = *(double *)&buff[0];
             wpt_tmp->position.latitude.degrees = (radians * 180.0) / M_PI;
 
             /* 8 bytes - longitude in radians */
-            fread(&buff[0], 1, 8, psp_file_in);
+            psp_fread(&buff[0], 1, 8, psp_file_in);
             radians = *(double *)&buff[0];
             wpt_tmp->position.longitude.degrees = (radians * 180.0) / M_PI;
 
             /* 1 byte - pin display properties */
-            fread(&buff[0], 1, 1, psp_file_in);
+            psp_fread(&buff[0], 1, 1, psp_file_in);
 
            /* 3 bytes - unknown */
-            fread(&buff[0], 1, 3, psp_file_in);
+            psp_fread(&buff[0], 1, 3, psp_file_in);
 
-           /* 1 bytes - icon 0x00 - 0x27 */
-            fread(&buff[0], 1, 1, psp_file_in);
+            /* 1 bytes - icon 0x00 - 0x27 */
+            psp_fread(&buff[0], 1, 1, psp_file_in);
 
            /* 3 bytes - unknown */
-           fread(&buff[0], 1, 3, psp_file_in);
+           psp_fread(&buff[0], 1, 3, psp_file_in);
 
             /* 1 byte - string size */
-           fread(&buff[0], 1, 1, psp_file_in);
+           psp_fread(&buff[0], 1, 1, psp_file_in);
 
            stringsize = buff[0];
            stringsize *= 2;
-           
+
            if (stringsize > MAXPSPSTRINGSIZE) {
                fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE);
            }
 
             /* stringsize bytes - string data */
-           fread(&buff[0], 1, stringsize, psp_file_in);
+           psp_fread(&buff[0], 1, stringsize, psp_file_in);
 
            buffer_washer(buff, stringsize);
 
-#ifdef _DEBUG_PSP
-           printf ("string1: [%s]\n", buff);
-#endif             
-
            wpt_tmp->shortname = strdup(buff);
 
             /* 1 bytes string size */
-           fread(&buff[0], 1, 1, psp_file_in);
+           psp_fread(&buff[0], 1, 1, psp_file_in);
 
            stringsize = buff[0];
            stringsize *= 2;
@@ -189,22 +206,15 @@ psp_read(void)
                fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE);
            }
 
-#ifdef _DEBUG_PSP
-           printf ("string2: there are %d bytes to follow at offset %ld\n", stringsize, ftell(psp_file_in));
-#endif
-
-            /* stringsize bytes - string data */            
-           fread(&buff[0], 1, stringsize, psp_file_in);
+            /* stringsize bytes - string data */
+           psp_fread(&buff[0], 1, stringsize, psp_file_in);
 
            buffer_washer(buff, stringsize);
 
-#ifdef _DEBUG_PSP
-           printf ("string2: [%s]\n", buff);
-#endif
            wpt_tmp->description = strdup(buff);
 
             /* 1 bytes - string size */
-           fread(&buff[0], 1, 1, psp_file_in);
+           psp_fread(&buff[0], 1, 1, psp_file_in);
 
            stringsize = buff[0];
            stringsize *= 2;
@@ -213,24 +223,13 @@ psp_read(void)
                fatal(MYNAME ": variable string size (%d) in PSP file exceeds MAX (%d).\n", stringsize, MAXPSPSTRINGSIZE);
            }
 
-
-#ifdef _DEBUG_PSP
-           printf ("string: there are %d bytes to follow at offset %ld\n", stringsize, ftell(psp_file_in));
-#endif
-
             /* stringsize bytes - string data (address?) */
-           fread(&buff[0], 1, stringsize, psp_file_in);
+           psp_fread(&buff[0], 1, stringsize, psp_file_in);
 
            buffer_washer(buff, stringsize);
 
-#ifdef _DEBUG_PSP
-           printf ("string3: [%s]\n", buff);
-#endif             
-           
-           waypt_add(wpt_tmp);
-       } 
-
-
+           waypt_add(wpt_tmp);
+       }
 }
 
 static void
@@ -248,11 +247,11 @@ psp_disp(waypoint *wpt)
         /* 4 leading bytes */
         memset(&tbuf, '\0', sizeof(tbuf));
         fwrite(&tbuf, 1, 4, psp_file_out);
-       
+
         /* my test files seem to always have this byte as 0x03, */
         /* although nothing seems to really care.               */
        c = 0x03;
-       
+
         /* 1 unknown bytes */
         fwrite(&c, 1, 1, psp_file_out);
 
@@ -263,13 +262,13 @@ psp_disp(waypoint *wpt)
         fwrite(&lon, 1, 8, psp_file_out);
 
         /* 1 byte - pin properties */
-        c = 0x14; /* display pin on! display notes on! */
+        c = 0x14; /* display pin name on! display notes on! */
         fwrite(&c, 1, 1, psp_file_out);
 
         memset(&tbuf, '\0', sizeof(tbuf));
 
         /* 3 unknown bytes */
-        fwrite(&tbuf, 1, 3, psp_file_out); 
+        fwrite(&tbuf, 1, 3, psp_file_out);
 
         /* 1 icon byte 0x00 = PIN */
         fwrite(&tbuf, 1, 1, psp_file_out);
@@ -279,7 +278,7 @@ psp_disp(waypoint *wpt)
 
         c = strlen(wpt->shortname);
         /* 1 string size */
-        fwrite(&c, 1, 1, psp_file_out); 
+        fwrite(&c, 1, 1, psp_file_out);
 
         for (i = 0 ; wpt->shortname[i] ; i++) {
              fwrite(&wpt->shortname[i], 1, 1, psp_file_out);    /* char */
@@ -298,13 +297,12 @@ psp_disp(waypoint *wpt)
         /* just for the hell of it, we'll scrap the third string. */
         c = strlen(tbuf);
         /* 1 byte string size */
-        fwrite(&c, 1, 1, psp_file_out); 
+        fwrite(&c, 1, 1, psp_file_out);
 
         for (i = 0 ; tbuf[i] ; i++) {
              fwrite(&tbuf[i], 1, 1, psp_file_out);              /* char */
              fwrite(&tbuf[0], 1, 1, psp_file_out);              /* null */
         }
-        
 }
 
 static void
@@ -318,16 +316,16 @@ psp_write(void)
         /* offset 0x0C - 0x0D = 2 byte pin count */
 
         s = waypt_count();
-        
+
         if (s > MAXPSPOUTPUTPINS) {
-            fatal(MYNAME ": output too many pushpins (%d).  The max is %d.  Sorry.\n", s, MAXPSPOUTPUTPINS);
+            fatal(MYNAME ": attempt to output too many pushpins (%d).  The max is %d.  Sorry.\n", s, MAXPSPOUTPUTPINS);
         }
 
         /* insert waypoint count into header */
         memcpy(&header_bytes[12], &s, 2);
 
         fwrite(&header_bytes, 1,  32, psp_file_out);
-        
+
         waypt_disp_all(psp_disp);
 }
 
index 30862b79b3f27bc5517e4651b0634db4c703dd7f..9560d48a662203948712b20cf103f275a849a38a 100755 (executable)
@@ -63,3 +63,11 @@ diff /tmp/ps.psp reference
 ${PNAME} -i mxf -f mxf.c -o mxf -F /tmp/mxf.mxf >/dev/null
 diff /tmp/mxf.mxf reference
 
+# MXF (Maptech Exchange Format) file format
+${PNAME} -i geo -f geocaching.loc -o mxf -F /tmp/mxf.mxf
+diff /tmp/mxf.mxf reference
+
+# MXF (Maptech Exchange Format) file format
+${PNAME} -i geo -f geocaching.loc -o mxf -F /tmp/mxf.mxf
+diff /tmp/mxf.mxf reference
+